import json
import requests
from flask import request, jsonify, current_app
from flasgger import swag_from
from app.api.v1 import api_v1
from app.models.user import User
from app.utils.wechat import decrypt_phone_number
from app.utils.decorators import login_required
from app.utils.auth_validator import AuthValidator
from app.api.v1.docs.auth_docs import LOGIN_DOC, BIND_PHONE_DOC, GET_USER_INFO_DOC, GET_TOKEN_DOC, REGISTER_DOC

# 在函数内部导入db，避免循环导入
def get_db():
    from app import db
    return db

@api_v1.route('/auth/info', methods=['GET'])
@swag_from(GET_TOKEN_DOC)
def auth_info():
    """认证说明接口"""
    return jsonify({
        'code': 200,
        'message': '认证说明',
        'data': {
            'description': '获取认证Token的步骤说明',
            'steps': [
                '1. 调用微信登录接口 /api/v1/user/login 获取session_key和openid',
                '2. 使用session_key和openid调用绑定手机号接口 /api/v1/user/phone',
                '3. 或者使用统一注册接口 /api/v1/user/register 一次性完成登录和手机号绑定',
                '4. 登录成功后，服务器会返回token，并在响应头中设置session cookie',
                '5. 后续请求需要在请求头中添加 Authorization: Bearer {token} 或在请求中包含session cookie'
            ],
            'auth_methods': {
                'header_token': {
                    'name': 'Authorization',
                    'format': 'Bearer {token}',
                    'example': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
                },
                'cookie_session': {
                    'name': 'Cookie',
                    'format': 'session={session_id}',
                    'example': 'session=abc123def456'
                }
            },
            'notes': [
                'token有效期为7天',
                '建议同时使用token和cookie进行认证',
                '如果token过期，需要重新登录获取',
                '推荐使用统一注册接口 /api/v1/user/register 简化流程'
            ]
        }
    })

@api_v1.route('/user/register', methods=['POST'])
@swag_from(REGISTER_DOC)
def user_register():
    """统一用户注册接口 - 一次性完成微信登录和手机号绑定"""
    db = get_db()
    data = request.get_json()
    
    try:
        # 验证必要参数
        required_fields = ['code', 'encryptedData', 'iv']
        if not data or not all(field in data for field in required_fields):
            return jsonify({'code': 400, 'message': '缺少必要参数：code, encryptedData, iv'}), 400
        
        # 清理输入数据
        data = AuthValidator.clean_user_input(data)
        
        code = data.get('code')
        encrypted_data = data.get('encryptedData')
        iv = data.get('iv')
        user_info = data.get('userInfo', {})
        
        # 验证微信code格式
        AuthValidator.validate_wechat_code(code)
        
        # 验证加密数据格式
        AuthValidator.validate_encrypted_data(encrypted_data, iv)
        
        # 验证用户信息
        AuthValidator.validate_user_info(user_info)
        
        # 检查注册频率
        AuthValidator.check_register_frequency()
    
    except ValueError as e:
        # 验证错误
        current_app.logger.warning(f"用户注册验证失败: {str(e)}")
        return jsonify({'code': 400, 'message': str(e)}), 400
    
    try:
        # 第一步：微信登录获取openid和sessionKey
        appid = current_app.config['WECHAT_APPID']
        secret = current_app.config['WECHAT_SECRET']
        #appid = 'wx72cb1f75487a2336'
        #secret = '64a08f0f7476b7986d732e6677e22ada'
        print(appid, secret)
        url = f'https://api.weixin.qq.com/sns/jscode2session?appid={appid}&secret={secret}&js_code={code}&grant_type=authorization_code'
        
        response = requests.get(url)
        result = response.json()
        
        if 'errcode' in result and result['errcode'] != 0:
            return jsonify({'code': 401, 'message': f"微信登录失败: {result.get('errmsg', '未知错误')}"}), 401
        
        openid = result.get('openid')
        session_key = result.get('session_key')
        
        if not openid:
            return jsonify({'code': 401, 'message': '获取openid失败'}), 401
        
        # 第二步：解密手机号
        phone_info = decrypt_phone_number(session_key, encrypted_data, iv)
        if not phone_info or 'phoneNumber' not in phone_info:
            return jsonify({'code': 400, 'message': '手机号解密失败'}), 400
        
        phone_number = phone_info['phoneNumber']
        
        # 验证手机号格式
        AuthValidator.validate_phone_number(phone_number)
        
        # 验证openid格式
        AuthValidator.validate_openid(openid)
        
        # 检查手机号注册频率
        AuthValidator.check_register_frequency(phone=phone_number)
        
        # 第三步：智能用户处理逻辑
        user = None
        is_new_user = False
        
        # 先根据openid查找用户
        user_by_openid = User.query.filter_by(openid=openid).first()
        # 再根据手机号查找用户
        user_by_phone = User.query.filter_by(phone=phone_number).first()
        
        if user_by_openid and user_by_phone:
            # 情况1：同时存在openid和手机号的用户
            if user_by_openid.id == user_by_phone.id:
                # 同一个用户，正常登录
                user = user_by_openid
                current_app.logger.info(f"用户重复登录: openid={openid}, phone={phone_number}")
            else:
                # 不同用户，数据冲突，记录详细信息
                current_app.logger.error(f"严重数据冲突: openid={openid} 对应用户{user_by_openid.id}, phone={phone_number} 对应用户{user_by_phone.id}")
                return jsonify({
                    'code': 400, 
                    'message': '账号数据异常，请联系客服处理',
                    'details': {
                        'conflict_type': 'data_inconsistency',
                        'phone': phone_number
                    }
                }), 400
        elif user_by_openid:
            # 情况2：只有openid用户存在，绑定手机号
            user = user_by_openid
            user.phone = phone_number
            current_app.logger.info(f"为已有微信用户绑定手机号: openid={openid}, phone={phone_number}")
        elif user_by_phone:
            # 情况3：只有手机号用户存在，绑定微信
            user = user_by_phone
            if user.openid and user.openid != openid:
                # 手机号已被其他微信号绑定，记录详细信息用于排查
                current_app.logger.warning(f"手机号绑定冲突: phone={phone_number}, 现有openid={user.openid}, 新openid={openid}")
                return jsonify({
                    'code': 400, 
                    'message': '该手机号已被其他微信账号绑定，如果您更换了微信账号，请联系客服处理',
                    'details': {
                        'conflict_type': 'phone_bound_to_different_wechat',
                        'phone': phone_number
                    }
                }), 400
            user.openid = openid
            current_app.logger.info(f"为已有手机号用户绑定微信: openid={openid}, phone={phone_number}")
        else:
            # 情况4：全新用户，创建新记录
            user = User(openid=openid, phone=phone_number)
            is_new_user = True
            
            # 设置用户基本信息
            if user_info:
                user.nickname = user_info.get('nickName')
                user.avatar_url = user_info.get('avatarUrl')
                user.gender = user_info.get('gender', 0)
            
            db.session.add(user)
            current_app.logger.info(f"创建新用户: openid={openid}, phone={phone_number}")
        
        # 确保用户有手机号
        if not user.phone:
            user.phone = phone_number
        
        # 如果是新用户且没有设置昵称，使用手机号作为默认昵称
        if is_new_user and not user.nickname:
            user.nickname = f"用户{phone_number[-4:]}"
        
        db.session.commit()
        
        return jsonify({
            'code': 200,
            'message': '注册成功' if is_new_user else '登录成功',
            'data': {
                'userId': user.id,
                'openid': openid,
                'sessionKey': session_key,
                'isNewUser': is_new_user,
                'phone': phone_number,
                'userInfo': user.to_dict(),
                'registerTime': user.created_at.strftime('%Y-%m-%d %H:%M:%S') if user.created_at else None
            }
        })
        
    except ValueError as e:
        # 验证错误
        current_app.logger.warning(f"用户注册验证失败: {str(e)}")
        return jsonify({'code': 400, 'message': str(e)}), 400
    
    except Exception as e:
        current_app.logger.error(f"用户注册异常: {str(e)}")
        db.session.rollback()
        return jsonify({'code': 500, 'message': '服务器错误'}), 500

@api_v1.route('/user/login', methods=['POST'])
@swag_from(LOGIN_DOC)
def user_login():
    """微信小程序登录接口"""
    db = get_db()
    data = request.get_json()
    if not data or 'code' not in data:
        return jsonify({'code': 400, 'message': '缺少必要参数'}), 400
    
    code = data.get('code')
    
    # 请求微信接口获取openid
    appid = current_app.config['WECHAT_APPID']
    secret = current_app.config['WECHAT_SECRET']
    url = f'https://api.weixin.qq.com/sns/jscode2session?appid={appid}&secret={secret}&js_code={code}&grant_type=authorization_code'
    
    try:
        response = requests.get(url)
        result = response.json()
        
        if 'errcode' in result and result['errcode'] != 0:
            return jsonify({'code': 401, 'message': f"微信登录失败: {result.get('errmsg', '未知错误')}"}), 401
        
        openid = result.get('openid')
        session_key = result.get('session_key')
        
        if not openid:
            return jsonify({'code': 401, 'message': '获取openid失败'}), 401
        
        # 查找或创建用户
        user = User.query.filter_by(openid=openid).first()
        if not user:
            user = User(openid=openid)
            db.session.add(user)
            db.session.commit()
        
        # 更新用户信息（如果请求中包含）
        if 'userInfo' in data:
            user_info = data.get('userInfo', {})
            user.nickname = user_info.get('nickName', user.nickname)
            user.avatar_url = user_info.get('avatarUrl', user.avatar_url)
            user.gender = user_info.get('gender', user.gender)
            db.session.commit()
        
        return jsonify({
            'code': 200,
            'message': '登录成功',
            'data': {
                'userId': user.id,
                'openid': openid,
                'sessionKey': session_key,
                'isNewUser': user.phone is None,
                'userInfo': user.to_dict()
            }
        })
    
    except Exception as e:
        current_app.logger.error(f"微信登录异常: {str(e)}")
        return jsonify({'code': 500, 'message': '服务器错误'}), 500


@api_v1.route('/user/phone', methods=['POST'])
@swag_from(BIND_PHONE_DOC)
def bind_phone():
    """绑定手机号"""
    db = get_db()
    data = request.get_json()
    if not data or 'openid' not in data or 'encryptedData' not in data or 'iv' not in data:
        return jsonify({'code': 400, 'message': '缺少必要参数'}), 400
    
    openid = data.get('openid')
    encrypted_data = data.get('encryptedData')
    iv = data.get('iv')
    session_key = data.get('sessionKey')
    
    user = User.query.filter_by(openid=openid).first()
    if not user:
        return jsonify({'code': 404, 'message': '用户不存在'}), 404
    
    try:
        # 解密手机号
        phone_info = decrypt_phone_number(session_key, encrypted_data, iv)
        if not phone_info or 'phoneNumber' not in phone_info:
            return jsonify({'code': 400, 'message': '手机号解密失败'}), 400
        
        phone_number = phone_info['phoneNumber']
        
        # 检查手机号是否已被其他用户绑定
        existing_user = User.query.filter_by(phone=phone_number).first()
        if existing_user and existing_user.id != user.id:
            return jsonify({'code': 400, 'message': '该手机号已被其他账号绑定'}), 400
        
        # 更新用户手机号
        user.phone = phone_number
        db.session.commit()
        
        return jsonify({
            'code': 200,
            'message': '手机号绑定成功',
            'data': {
                'userId': user.id,
                'phone': phone_number,
                'userInfo': user.to_dict()
            }
        })
    
    except Exception as e:
        current_app.logger.error(f"手机号绑定异常: {str(e)}")
        return jsonify({'code': 500, 'message': '服务器错误'}), 500


@api_v1.route('/user/info', methods=['GET'])
@swag_from(GET_USER_INFO_DOC)
@login_required
def get_user_info():
    """获取用户信息"""
    user_id = request.args.get('userId')
    user = User.query.get(user_id)
    
    if not user:
        return jsonify({'code': 404, 'message': '用户不存在'}), 404
    
    return jsonify({
        'code': 200,
        'message': '获取成功',
        'data': user.to_dict()
    })